package com.xc.stock.infrastructure.redis.config;

import java.io.IOException;
import java.time.Duration;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.spring.data.connection.RedissonConnectionFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.xc.stock.aop.distributedlock.DistributedLockTemplate;
import com.xc.stock.infrastructure.redis.SingleDistributedLockTemplate;
import com.xc.stock.utils.Env;
import com.xc.utils.PropertiesUtil;

/**
 * 
 * @author xlfd
 * @email xlfd@gmail.com
 * @version 1.0  
 * @created Jun 3, 2021 4:56:28 PM
 */
@Configuration
@EnableCaching
public class RedisConfig {
	@Bean
    @ConditionalOnMissingBean(RedisConnectionFactory.class)
    public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
        return new RedissonConnectionFactory(redisson);
    }

	@Bean
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(redisConnectionFactory);
		redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		
		redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
		
		return redisTemplate;
	}

	@Bean
	public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
		// 配置序列化
		RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
		config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
		config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class)));

		// 设置缓存的默认过期时间 ,30分钟
		config.entryTtl(Duration.ofMinutes(30));
		// 不缓存空值
		config.disableCachingNullValues();
		RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config)
				.build();
		return cacheManager;
	}
	
	@Lazy
	@Bean
    public RedissonClient getRedissonClient(Env env) throws IOException {
        Config config = new Config();
        /**
         * redis1.ip=43.128.20.12
			redis1.port=36379
			redis1.pwd=ruTZ9J3gaDhknJ
         */
        String ip = PropertiesUtil.getProperty(env, "redis1.ip", null);
        String port = PropertiesUtil.getProperty(env, "redis1.port", null);
        String pwd = PropertiesUtil.getProperty(env, "redis1.pwd", null);
        
        config.useSingleServer()
        	.setAddress("redis://" + ip + ":" + port)
        	.setPassword(pwd)
        	;
        return Redisson.create(config);
    }
	
	/**
	 * 分布式锁实现 
	 * @param redissonClient
	 * @return
	 */
	@Lazy
	@Bean
	public DistributedLockTemplate distributedLockTemplate(RedissonClient redissonClient) {
	    return new SingleDistributedLockTemplate(redissonClient);
	}
}
